﻿#define Tt_TableView
#undef  Tt_TableView

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System;
using System.Collections.Generic;


[RequireComponent(typeof(ScrollRect))]
public class TableViewControl : MonoBehaviour
{

    [SerializeField]
    private GridLayoutGroup.Axis m_startAxis = GridLayoutGroup.Axis.Vertical;
    [SerializeField]
    private GameObject m_cellTemplate;
    private RectTransform m_contentRT;
    private Dictionary<int, TableCellData> m_activityCells = new Dictionary<int, TableCellData>();
    private RectTransform m_scrollRect;
    private RectTransform goRT;
    private int m_cellCount;
    private int m_createCellCount;
    private List<int> unuseKey = new List<int>();
    private bool m_isInit;

    public bool IsInit
    {
        get { return m_isInit; }
        set { m_isInit = value; }
    }



    #region 属性
    public event Action<TableViewControl, TableCellData> UpdateEvent;
    public int Count
    {
        get { return m_cellCount; }
        set { m_cellCount = value; }
    }
    public int CreateCellCount
    {
        get { return m_createCellCount; }
        set { m_createCellCount = value; }
    }
    public RectTransform ContentRT
    {
        get 
        {
            if(m_contentRT == null)
                m_contentRT = (RectTransform)GetComponent<ScrollRect>().content.transform;

            return m_contentRT;
        }
        set { m_contentRT = value; }
    }
    #endregion



    public void Awake()
    {

    }

    public void Init(int count, int createCount, bool isCreateCell = true)
    {
        m_cellCount = count;
        m_createCellCount = createCount;
        ClearCell();

        if (isCreateCell) { 
            CreateCell();
            IsInit = true;
        }

    }

    public void CreateCell()
    {
        GameObject go = null;

        float width = 0f;
        float height = 0f;
        float pivotX = 0f;
        float pivotY = 0f;

        TableCellData cellData = null;

        for (int i = m_activityCells.Count; i < CreateCellCount; i++)
        {
            go = GameObject.Instantiate(m_cellTemplate) as GameObject;
            go.transform.SetParent(ContentRT.transform, false);
            go.name += i;
            goRT = go.GetComponent<RectTransform>();

            width = goRT.sizeDelta.x;
            height = goRT.sizeDelta.y;
            pivotX = goRT.pivot.x;
            pivotY = goRT.pivot.y;

            if (m_startAxis == GridLayoutGroup.Axis.Horizontal)
            {
                goRT.anchoredPosition = new Vector3(i * width + width * pivotX, goRT.anchoredPosition.y, 0);
            }
            else if (m_startAxis == GridLayoutGroup.Axis.Vertical)
            {
                goRT.anchoredPosition = new Vector3(goRT.anchoredPosition.x, -i * height - height * (1 - pivotY), 0);
            }


            go.SetActive(true);
            cellData = new TableCellData()
            {
                Index = i,
                Cell = go
            };

            m_activityCells.Add(i, cellData);

            if (UpdateEvent != null)
            {
                UpdateEvent(this, cellData);
            }
        }

        if (goRT != null)
        {
            //int cellCount = Count == 0 ? CreateCellCount : Count;
            if (m_startAxis == GridLayoutGroup.Axis.Horizontal)
            {
                ContentRT.sizeDelta = new Vector3(Count * goRT.sizeDelta.x, ContentRT.sizeDelta.y);   

            }
            else if (m_startAxis == GridLayoutGroup.Axis.Vertical)
            {
                ContentRT.sizeDelta = new Vector2(ContentRT.sizeDelta.x, Count * goRT.sizeDelta.y);
            }
        }
    }


    private int newIndex = 0;
    private int curIndex = 0;
    public void FixedUpdate()
    {
        MoveRefreshData();
    }

    private void MoveRefreshData()
    {
        if (goRT != null)
        {
            if (m_startAxis == GridLayoutGroup.Axis.Horizontal)
            {
                newIndex = (int)(-ContentRT.anchoredPosition.x / goRT.sizeDelta.x);
            }
            else if (m_startAxis == GridLayoutGroup.Axis.Vertical)
            {
                newIndex = (int)(ContentRT.anchoredPosition.y / goRT.sizeDelta.y);
            }


            if (newIndex == curIndex)
                return;

            if (m_cellCount <= m_createCellCount)
            {

                return;
            }

            if (newIndex < 0)
            {
                if (curIndex == 0)
                {
                    return;
                }

                curIndex = 0;
                newIndex = 0;
            }
            else if (newIndex > m_cellCount - m_createCellCount)
            {
                if (curIndex == m_cellCount - m_createCellCount)
                {
                    return;
                }

                newIndex = m_cellCount - m_createCellCount;
            }


            curIndex = newIndex;
            //把看不到的单元格,加入无用数组中
            foreach (var index in m_activityCells.Keys)
            {
                if (index >= newIndex && index < newIndex + m_createCellCount)
                    continue;

                if (!unuseKey.Contains(index)) {
                    unuseKey.Add(index);
                    //Debug.Log("添加无用单元格: "  + index);
                }
            }



            int idx = 0;
            TableCellData go = null;
            RectTransform rect = null;
            for (int i = 0; i < m_createCellCount; i++)
            {
                idx = newIndex + i;
                if (m_activityCells.ContainsKey(idx)) { 
                    continue;
                }

                go = m_activityCells[unuseKey[0]];
                m_activityCells.Remove(unuseKey[0]);
                m_activityCells.Add(idx, go);
                unuseKey.RemoveAt(0);
                go.Cell.name = "Cell" + idx;
                go.Index = idx;
                rect = go.Cell.GetComponent<RectTransform>();

                if (m_startAxis == GridLayoutGroup.Axis.Horizontal)
                {
                    rect.anchoredPosition = new Vector3(idx * rect.sizeDelta.x + rect.sizeDelta.x * rect.pivot.x, rect.anchoredPosition.y, 0);
                }
                else if (m_startAxis == GridLayoutGroup.Axis.Vertical)
                {
                    rect.anchoredPosition = new Vector3(rect.anchoredPosition.x, -idx * rect.sizeDelta.y - rect.sizeDelta.y * rect.pivot.y, 0);
                }


                if (UpdateEvent != null)
                    UpdateEvent(this, go);
            }
        }
    }

    public void RefreshData()
    {
        foreach (var item in m_activityCells)
        {
            if (UpdateEvent != null)
            {
                UpdateEvent(this, item.Value);
            }
        }
    }

    public void ClearCell(int startIndex = 0)
    {
        if (startIndex >= m_activityCells.Count)
            return;

        int index = 0;
        int[] len = new int[m_activityCells.Count - startIndex];
        int k = 0;

        foreach (var item in m_activityCells)
        {
            if (index >= startIndex)
            {
                len[k] = item.Key;
                GameObject.DestroyImmediate(item.Value.Cell);
                k++;
            }
            index++;
        }

        for (int i = 0; i < len.Length; i++)
            m_activityCells.Remove(len[i]);


        IsInit = false;
    }


    public TableCellData GetCell(int index)
    {
        if (!m_activityCells.ContainsKey(index))
            return null;

        return m_activityCells[index];
    }

    public Dictionary<int, TableCellData> GetActivityCells()
    {
        return m_activityCells;
    }
}

public class TableCellData
{
    public int Index { get; set; }
    public GameObject Cell { get; set; }
}